package com.apes.scm.stock.transfer.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.transit.DepositInTransitService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.enumeration.model.Enumeration;
import com.apes.scm.masterdata.frame.service.StoreService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.service.PartyRoleService;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.product.service.UomService;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import com.apes.scm.rbac.repository.UserRepository;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.PickItem;
import com.apes.scm.stock.transfer.model.Transfer;
import com.apes.scm.stock.transfer.model.TransferItem;
import com.apes.scm.stock.transfer.repository.PickRepository;
import com.apes.scm.stock.transfer.repository.TransferItemRepository;
import com.apes.scm.stock.transfer.repository.TransferRepository;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 内部转储
 *
 * @author wuq
 * @create 2018-06-22 10:56
 */
@Service("transferService")
public class TransferService extends DomainService {

    @Autowired
    TransferRepository transferRepository;

    @Autowired
    ProductAccountService productAccountService;

    @Autowired
    PickRepository pickRepository;

    @Autowired
    ContractRepository contractRepository;

    @Autowired
    PartyRoleService partyRoleService;

    @Autowired
    ProductRepository productRepository;

    @Autowired
    ProductUomRepository productUomRepository;

    @Autowired
    TransferItemRepository transferItemRepository;

    @Autowired
    UomService uomService;
    @Autowired
    private DepositInTransitService depositInTransitService;

    @Autowired
    StockRepository stockRepository;
    @Autowired
    private StoreService storeService;
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 功能：保存转储订单
     *
     * @param request
     * @return
     */
    public Transfer create(SimpleRequest request) {
        Transfer order = request.getO(Transfer.class);
        Assert.isTrue(order.getTransferItems().size() < 100, "转储商品上限100条！超100请从 '批量补货' 功能导入");
//        order.setCreator(request.getPersonId());
        // 检查明细发货数量大于0
        for (TransferItem item : order.getTransferItems()) {
            if (item.getTransferQty() == 0) {
                throw new RuntimeException("商品编码【" + item.getProduct().getId() + "】转储数量为0，请检查！");
            }
        }
        //设置转储订单类型
        order.setScene(SpringManager.getBean(SceneRepository.class).findOne("PT001"));

        order.setState("sent");
        order.setCreateDate(new Date());
        if (order.getCreator() == null) order.setCreator(this.getPersonId(request));

        // 对跨公司进行检查
        if (order.checkCross()) {

            if (checkForwardContract(order)) {
                // 正向调拨
                order.setTransferDirection("forward");
            } else if (checkReverseContract(order)) {
                // 反向调拨
                order.setTransferDirection("reverse");
            } else {
                throw new RuntimeException("请检查发货公司与收货公司间的合同!");
            }

        }
        if (order.getCreateUid() == null) order.setCreateUid(request.getPerson());
        order.setUserId(SpringManager.getBean(UserRepository.class).findOne(JpaDsl.toCriteriaByEq("person.id", order.getCreateUid().getId())).get().getId() + "");

        order = transferRepository.saveAndFlush(order); // 后面需要使用到单号

        // 写入可用数
        updateProductAvailable(order, -1);

        // 批量补货可能存在所有明细数据异常
        if (order.getTransferItems().isEmpty()) {
            transferRepository.delete(order);
            return new Transfer();
        }

        if ("BatchDump".equals(order.getSourceBusinessType())) order = transferRepository.saveAndFlush(order);

        // 未达帐
        saveDepositInTransit(order);

        /**增加收货仓的转入制单数*/
        changeInBilling(order,1);
        return order;
    }

    // 批量补货 - 创建转储
    public Transfer createBatchDump(SimpleRequest request) {
        Map getM = request.getMap();
        SimpleRequest transferData = new SimpleRequest();
        transferData.setData(getM.get("transferNew"));
        return this.create(transferData);
//        return invoke("stock.transfer.create", getM.get("transferNew"));
    }

    /**
     * 未达帐
     **/
    private void saveDepositInTransit(Transfer transfer) {
//        DepositInTransitService depositInTransitService = SpringManager.getBean(DepositInTransitService.class);
        transfer.getTransferItems().stream().forEach(item -> {
            double occurQty = productAccountService.computeQtyUnit(transfer.getCompany(), item.getProduct(), item.getUom(), item.getTransferQty());
            depositInTransitService.save(transfer.getCompany(), transfer.getOriginLocation(), transfer.getReceiptLocation().getDepot().getDept(), transfer.getInnerBusinessType(), transfer.getInnerBusinessKey(),
                    String.valueOf(item.getId()), item.getProduct(), occurQty, "发货");
            depositInTransitService.save(transfer.getCompany(), transfer.getReceiptLocation(), transfer.getOriginLocation().getDepot().getDept(), transfer.getInnerBusinessType(), transfer.getInnerBusinessKey(),
                    String.valueOf(item.getId()), item.getProduct(), occurQty, "收货");
        });
    }

    /**
     * 检查正向合同
     * 正向流程： 发货仓的 销售合同，收货仓的 采购合同
     *
     * @param transfer 转储订单
     */
    public boolean checkForwardContract(Transfer transfer) {
        boolean flag = false;

        PartyRole originCompany = transfer.getOriginLocation().getCompany();   // 发货公司
        PartyRole receiptCompany = transfer.getReceiptLocation().getCompany(); // 收货公司

        // 发货仓 处于有效期内销售合同
        PartyRole customer = partyRoleService.findByPartyAndRole(receiptCompany.getParty().getId(), "Customer");
        if (customer == null) throw new RuntimeException("没有找到发货仓库对应的 PartyRole");
        List<Contract> customerContractList = contractRepository.findAllByCompanyAndPartner(originCompany.getId(), customer.getId(), new Date());
        if (customerContractList.size() == 0) return flag;    // 没有销售合同
        Contract customerContract = customerContractList.get(0);

        // 收货仓 处于有效期内采购合同
        PartyRole supplier = partyRoleService.findByPartyAndRole(originCompany.getParty().getId(), "Supplier");
        if (customer == null) throw new RuntimeException("没有找到收货仓库对应的 PartyRole");
        List<Contract> supplierContractList = contractRepository.findAllByCompanyAndPartner(receiptCompany.getId(), supplier.getId(), new Date());
        if (supplierContractList.size() == 0) return flag;    // 没有采购合同
        Contract supplierContract = supplierContractList.get(0);

        if ("customer".equals(customerContract.getContractType().getCode()) &&
                "supplier".equals(supplierContract.getContractType().getCode())) {
            flag = true;
        }

        return flag;
    }

    /**
     * 检查逆向合同
     * 逆向流程： 发货仓的 采购合同，收货仓的 销售合同
     *
     * @param transfer 转储订单
     */
    public boolean checkReverseContract(Transfer transfer) {
        boolean flag = false;

        PartyRole originCompany = transfer.getOriginLocation().getCompany();   // 发货公司
        PartyRole receiptCompany = transfer.getReceiptLocation().getCompany(); // 收货公司

        //  收货仓 销售合同
        PartyRole customer = partyRoleService.findByPartyAndRole(originCompany.getParty().getId(), "Customer");

        List<Contract> customerContractList = contractRepository.findAllByCompanyAndPartner(receiptCompany.getId(), customer.getId(), new Date());
        if (customerContractList.size() == 0) return flag;    // 没有销售合同
        Contract customerContract = customerContractList.get(0);

        // 发货仓 采购合同
        PartyRole supplier = partyRoleService.findByPartyAndRole(receiptCompany.getParty().getId(), "Supplier");
        List<Contract> supplierContractList = contractRepository.findAllByCompanyAndPartner(originCompany.getId(), supplier.getId(), new Date());
        if (supplierContractList.size() == 0) return flag;    // 没有采购合同
        Contract supplierContract = supplierContractList.get(0);

        if ("customer".equals(customerContract.getContractType().getCode()) &&
                "supplier".equals(supplierContract.getContractType().getCode())) {
            flag = true;
        }

        return flag;
    }

    /**
     * 功能：修改转储订单
     *
     * @param request
     * @return
     */
    public Transfer update(SimpleRequest request) {
        Transfer order = request.getO(Transfer.class);

        // 检查明细发货数量大于0
        for (TransferItem item : order.getTransferItems()) {
            if (item.getTransferQty() == 0) {
                throw new RuntimeException("商品编码【" + item.getProduct().getId() + "】转储数量为0，请检查！");
            }
        }
        checkSaveData(order);   // 检查数量

        Transfer oldInnerTransfer = checkUpdateData(request, "update");
        //还原之前的可用数
        //updateProductAvailable(oldInnerTransfer, 1);
        oldInnerTransfer.getTransferItems().stream().forEach(
                (TransferItem item) ->
                        productAccountService.setProductAvailable(
                                item.getProduct(), oldInnerTransfer.getOriginLocation(), item.getUom(),
                                item.getTransferQty(), oldInnerTransfer.getInnerBusinessType(),
                                oldInnerTransfer.getId(),
                                String.valueOf(item.getId()),
                                "转储订单编辑",
                                oldInnerTransfer.getOriginLocation().getCompany())

        );
        /**还原收货仓的转入制单数*/
        changeInBilling(oldInnerTransfer,-1);

        /**删除未达帐**/
//        DepositInTransitService depositInTransitService = SpringManager.getBean(DepositInTransitService.class);
        oldInnerTransfer.getTransferItems().stream().forEach(item -> {
            depositInTransitService.delete(oldInnerTransfer.getInnerBusinessType(), oldInnerTransfer.getInnerBusinessKey(),
                    String.valueOf(item.getId()), oldInnerTransfer.getOriginLocation());
            depositInTransitService.delete(oldInnerTransfer.getInnerBusinessType(), oldInnerTransfer.getInnerBusinessKey(),
                    String.valueOf(item.getId()), oldInnerTransfer.getReceiptLocation());
        });

        //写入新的可用数
        //updateProductAvailable(order, -1);
        order.getTransferItems().stream().forEach(
                (TransferItem item) ->
                        productAccountService.setProductAvailable(
                                item.getProduct(), order.getOriginLocation(), item.getUom(),
                                item.getTransferQty()*-1, order.getInnerBusinessType(),
                                order.getId(),
                                String.valueOf(item.getId()),
                                "转储订单编辑",
                                order.getOriginLocation().getCompany())

        );
        /**增加收货仓的转入制单数*/
        changeInBilling(order,1);
        /**未达帐**/
        saveDepositInTransit(order);

        return transferRepository.saveAndFlush(order);
    }

    /**
     * 报错检查数据
     *
     * @param order 订单数据
     */
    private void checkSaveData(Transfer order) {
        String originCompanyId = order.getOriginLocation().getCompany().getId();
        String receiptCompanyId = order.getReceiptLocation().getCompany().getId();
        if (originCompanyId != receiptCompanyId) {
            throw new RuntimeException("不予许创建跨公司的订单。");
        }

        // 检查明细是否存在 数量为 0
        List<TransferItem> innerTransferItems = order.getTransferItems().stream()
                .filter(item -> item.getTransferQty() == 0)
                .collect(Collectors.toList());
        if (innerTransferItems.size() > 0) {
            throw new RuntimeException("商品编码为:" + innerTransferItems.get(0).getProduct().getId() + " 转储数量为0，请检查！");
        }
    }

    /**
     * 检查数据是否已经被修改
     *
     * @param request
     * @return
     */
    private Transfer checkUpdateData(SimpleRequest request, String operatorType) {
        Transfer oldInnerTransfer = new Transfer();
        String id = "";
        int version = -1;
        if (request.getData() != null) {
            oldInnerTransfer = request.getO(Transfer.class);
            id = oldInnerTransfer.getId();
            version = oldInnerTransfer.getVersion();
        } else {
            id = request.get("id");
            version = request.get("version");
        }
        oldInnerTransfer = transferRepository.findOne(id);
        if (oldInnerTransfer == null) throw new RuntimeException("转储订单【" + id + "】在系统中不存在。");
        if (oldInnerTransfer.getVersion() != version) throw new RuntimeException("记录已更新或已删除，请重新提交！");

        if ("delete".equals(operatorType)) return oldInnerTransfer;
        storeService.judgeFCKBJ(oldInnerTransfer.getOriginLocation());
        storeService.judgeFCKBJ(oldInnerTransfer.getReceiptLocation());
        return oldInnerTransfer;
    }

    /**
     * 功能：删除转储订单
     *
     * @param request
     * @return
     */
    public Transfer delete(SimpleRequest request) {
        // 检查数据
        checkUpdateData(request, "delete");
        Transfer transfer = request.getO(Transfer.class);
        transfer.setState("delete");
        transfer.setCreateDate(new Date());

        // 还原可用数、修改转入制单数量、删除未达帐
        transfer.getTransferItems().stream().forEach(item -> this.deleteChangeStockQty(transfer, item));
        transferRepository.saveAndFlush(transfer);
        return new Transfer();
    }

    // 删除修改相关账目
    private void deleteChangeStockQty(Transfer transfer, TransferItem item) {
        // 还原可用数
        productAccountService.setProductAvailable(
                item.getProduct(), transfer.getOriginLocation(), item.getUom(),
                item.getTransferQty(), transfer.getInnerBusinessType(),
                transfer.getId(), String.valueOf(item.getId()),
                "转储订单删除",
                transfer.getOriginLocation().getCompany());

        // 修改转入制单数量
        productAccountService.setProductTransferInBilling(item.getProduct(),
                transfer.getReceiptLocation(), item.getUom(), -1 * item.getTransferQty(),
                transfer.getReceiptLocation().getCompany());

        // 删除未达帐
        this.changeDepositInTransit(transfer.getInnerBusinessType(), transfer.getInnerBusinessKey(), item.getId(), transfer.getOriginLocation(), transfer.getReceiptLocation());
    }

    /**
     * 终止
     */
    public Transfer termination(SimpleRequest request) {
        Transfer transfer = request.getO(Transfer.class);
        Transfer qryTransfer = transferRepository.findOne(transfer.getId());
        if (!canTermination(transfer.getId()) || transfer.getVersion() != qryTransfer.getVersion()) throw new RuntimeException("单据状态已变更，请刷新！");
        transfer.setStopUid(request.getPerson());
        //因为店内转储审核后会自动收货，所以店内类型无法终止
        if ("000166".equals(transfer.getTransferType().getId())) throw new RuntimeException("店内转储无法终止!");
        boolean flag = false;

        for (TransferItem transferItem : qryTransfer.getTransferItems()) {
            if (transferItem.getTransferQty() != transferItem.getSendQty()) flag = true;
        }
        if (!flag) throw new RuntimeException("商品已全部发货，无法终止");

        double transferQty = 0;
        double finishQty = 0;
        double remainingShipQty = 0;
        for (TransferItem item:transfer.getTransferItems()) {
            transferQty += item.getTransferQty();
            double canTerminationQty = item.getTransferQty() - item.getSendQty() - item.getFinishSum();
            finishQty += item.getQtyReceived() + (canTerminationQty == 0?item.getFinishSum():item.getFinishSum() + canTerminationQty);
            if (canTerminationQty <= 0) continue;
            item.setFinishSum(item.getFinishSum() + canTerminationQty);
            remainingShipQty += item.getTransferQty() - item.getSendQty() - item.getFinishSum(); // 重新计算是否还有可生成交货单的数量

            // 删除未达账、减少转入制单数量、写商品库存帐可用数
            deposiAndTransferBillAndProductAvailable(transfer, item, canTerminationQty);

            // 来源安全库存缺口 - 修改要货分配数量
            this.sendUpdateGapAssignedQty(transfer.getSpecialDocumentsType(), item, -1 * item.getFinishSum());

            // 来源安全库存缺口 - 修改要货扩展表取消数量
            this.stopSendUpdateRequireExpandAssignedQty(transfer.getId(), transfer.getSpecialDocumentsType(), item);
        }
        transfer.setState(transferQty != finishQty?"approve":"done");
        transfer.setItemQtyComplete(remainingShipQty == 0?true:false);

        //取消交货单
        JSONObject tempJson = new JSONObject();
        List<Map> items = this.makeupPick(tempJson, transfer);
        if (items.size() == 0) return transfer;
        tempJson.put("items", items);
        tempJson.put("operation","deliver");
        invoke("stock.pick.dumpCancel", tempJson);

        Transfer newTransfer = transferRepository.saveAndFlush(transfer);

        // 来源要货单 - 要货转储要货明细数量、扩展数量更改
        this.terminationNoticRequireAndRequireExpand(newTransfer);
        return newTransfer;
    }

    private boolean canTermination(String transferId) {
        // 是否有对应交货单
        String sql = "" +
                "SELECT 1 " +
                "  FROM STOCK_TRANSFER A, STOCK_TRANSFER_ITEM B, " +
                "       (SELECT ORIGIN, ORIGIN_LINE, PRODUCT_ID, SUM(PRODUCT_UOM_QTY) QTY_DONE " +
                "           FROM STOCK_PICK J, STOCK_PICK_ITEM K " +
                "          WHERE J.ID = K.PICK_ID " +
                "            AND OPERATION = 'deliver' " +
                "            AND J.STATE = 'confirmed' " +
                "          GROUP BY ORIGIN, ORIGIN_LINE, PRODUCT_ID) C " +
                " WHERE A.ID = B.TRANSFER_ID AND A.ID = C.ORIGIN " +
                "   AND B.ID = C.ORIGIN_LINE " +
                "   AND A.ID = '" + transferId + "' " +
                "   AND B.TRANSFER_QTY - SEND_QTY - FINISH_SUM != C.QTY_DONE ";
        List noTermination = transferRepository.findAll(sql);
        if (noTermination.size() > 0) return false;


        // 发货数量是否一致
        sql = "" +
                "SELECT SEND_QTY, C.QTY_DONE " +
                "  FROM STOCK_TRANSFER A, STOCK_TRANSFER_ITEM B, " +
                "       (SELECT ORIGIN, ORIGIN_LINE, PRODUCT_ID, SUM(QTY_DONE) QTY_DONE " +
                "           FROM STOCK_PICK J, STOCK_PICK_ITEM K " +
                "          WHERE J.ID = K.PICK_ID " +
                "            AND OPERATION = 'deliver' " +
                "            AND J.STATE = 'done' AND WITHDRAW_UID IS NULL " +
                "          GROUP BY ORIGIN, ORIGIN_LINE, PRODUCT_ID) C " +
                " WHERE A.ID = B.TRANSFER_ID " +
                "   AND A.ID = C.ORIGIN " +
                "   AND B.ID = C.ORIGIN_LINE " +
                "   AND A.ID = '"+ transferId +"' " +
                "   AND SEND_QTY != C.QTY_DONE ";
        noTermination = transferRepository.findAll(sql);
        if (noTermination.size() > 0) return false;
        return true;
    }

    // 删除未达账、减少转入制单数量、写商品库存帐可用数
    private void deposiAndTransferBillAndProductAvailable(Transfer transfer, TransferItem item, double canTerminationQty) {
        // 写商品库存帐可用数
        productAccountService.setProductAvailable(
                item.getProduct(), transfer.getOriginLocation(), item.getUom(),
                canTerminationQty * 1, transfer.getInnerBusinessType(),
                transfer.getId(),
                String.valueOf(item.getId()),
                item.getFinishSum() == 0?"".equals(item.getNote()) || item.getNote() == null ? "转储订单制单" : item.getNote():"转储订单终止",
                transfer.getOriginLocation().getCompany());

        // 减少转入制单数
//        transfer.getTransferItems().forEach(orderItem-> {
            productAccountService.setProductTransferInBilling(item.getProduct(),
                    transfer.getReceiptLocation(), item.getUom(), -1 * canTerminationQty,
                    transfer.getReceiptLocation().getCompany());
//        });

        // 删除未达帐
        this.changeDepositInTransit(transfer.getInnerBusinessType(), transfer.getInnerBusinessKey(), item.getId(), transfer.getOriginLocation(), transfer.getReceiptLocation());
    }

    /**
     * 拼接交货信息
     * @param tempJson
     * @param order
     * @return
     */
    private List<Map> makeupPick(JSONObject tempJson, Transfer order) {
        tempJson.put("id", order.getId());
        tempJson.put("innerBusinessType", order.getInnerBusinessType());
        List<Map> items = order.getTransferItems().stream().filter(transferItem -> transferItem.getTransferQty() - transferItem.getSendQty() > 0)
                .map(transferItem -> {
                    Map pickItem = new HashMap();
                    pickItem.put("id", transferItem.getId());
                    pickItem.put("cancelQty", transferItem.getFinishSum());
                    return pickItem;
                }).collect(Collectors.toList());
        return items;
    }

    /**
     * 功能：审核转储订单
     *
     * @return
     */
    public Transfer approve(SimpleRequest request) {
        // 检查数据
        checkUpdateData(request, "approve");
        Transfer transfer = request.getO(Transfer.class);
        transfer.setState("approve");
        transfer.setApproveDate(new Date());
        if (transfer.getApproveUid() == null) transfer.setApproveUid(this.getPerson(request));

        transfer.setUserId(SpringManager.getBean(UserRepository.class).findOne(JpaDsl.toCriteriaByEq("person.id", transfer.getApproveUid().getId())).get().getId() + "");

        transfer = transferRepository.saveAndFlush(transfer);

        // 要货批量转储处理
        this.batchRequireDumpUpdateRequireQty(transfer);

        // 安全库存缺口
        this.updateOtherTable(transfer);
        return transfer;
    }

    /**写入库存账的转储发货在途、转储收货在途*/
    public void changeStock(Transfer transfer, TransferItem transferItem, double qtyDOne, int typeValue) {
//        transfer.getTransferItems().stream().forEach(transferItem -> {
            //商品库存帐转储发货在途
            productAccountService.setProductTransferIssue(transferItem.getProduct(),transfer.getOriginLocation(),transferItem.getUom(),
                    typeValue * qtyDOne, transfer.getCompany());
            //商品库存帐转储收货在途
            productAccountService.setProductTransferReceive(transferItem.getProduct(),transfer.getReceiptLocation(),transferItem.getUom(),
                    typeValue * qtyDOne,transfer.getCompany());
//        });
    }

    /** 收发货在途修改 */
    private void updateDumpTransit(Location originLocation, Location receiptLocation, Product product, ProductUom uom, double number) {
        // 发货在途
        productAccountService.setProductTransferIssue(product, originLocation, uom, number, originLocation.getCompany());

        // 收货在途
        productAccountService.setProductTransferReceive(product, receiptLocation, uom, number, receiptLocation.getCompany());
    }


    /**
     * 功能：写入可用数
     *
     * @param transfer  转储订单数据
     * @param typeValue -1 或者 1， -1 表示减少，1 表示增加
     */
    private void updateProductAvailable(Transfer transfer, int typeValue) {
        List errorItemIds = new ArrayList();
        transfer.getTransferItems().stream().forEach(
                (TransferItem item) -> {
                    double changeQty = item.getTransferQty() * typeValue;
                    PartyRole originLocaCompa = transfer.getOriginLocation().getCompany();
                    String message = item.getFinishSum() == 0?"".equals(item.getNote()) || item.getNote() == null ? "转储订单制单" : item.getNote():"转储订单终止";
                    try {
                        productAccountService.setProductAvailable(item.getProduct(), transfer.getOriginLocation(), item.getUom(), changeQty,
                                transfer.getInnerBusinessType(), transfer.getId(), String.valueOf(item.getId()), message, originLocaCompa);
                    } catch (Exception e) {
                        if (LogicalUtil.notIn(transfer.getSourceBusinessType(), "BatchDump")) throw new RuntimeException(e.getMessage());

                        // 异常立马加回
                        productAccountService.setProductAvailable(item.getProduct(), transfer.getOriginLocation(), item.getUom(), -1 * changeQty,
                                transfer.getInnerBusinessType(), transfer.getId(), String.valueOf(item.getId()), "批量补货 - 异常增回", originLocaCompa);

                        invoke("scm.transfer.batchDumpTransferService.invokeUpdate",
                                MapUtil.mapper("NOTE", e.getMessage(), "BATCH_DUMP_ID", transfer.getSource(), "RECEIPT_LOCATION_ID", transfer.getReceiptLocation().getId(), "PRODUCT_ID", item.getProduct().getId()));
                        errorItemIds.add(item.getId());
                    }
        });

        if (!errorItemIds.isEmpty()) this.removeErrorItem(transfer.getTransferItems(), errorItemIds);
    }

    // 迭代删除错误数据
    private void removeErrorItem(Set<TransferItem> items, List removeItemIds) {
        Iterator<TransferItem> iTransferItem = items.iterator();
        while (iTransferItem.hasNext()) {
            TransferItem item = iTransferItem.next();
            if (removeItemIds.contains(item.getId())) iTransferItem.remove();
        }
    }

    private void updateProductAvailableBytermination(Transfer transfer, int typeValue) {
        transfer.getTransferItems().stream().filter(transferItem -> transferItem.getSendQty() == 0).forEach(
                (TransferItem item) ->
                        productAccountService.setProductAvailable(
                                item.getProduct(), transfer.getOriginLocation(), item.getUom(),
                                item.getTransferQty() * typeValue, transfer.getInnerBusinessType(),
                                transfer.getId(),
                                String.valueOf(item.getId()),
                                item.getFinishSum() == 0?"".equals(item.getNote()) || item.getNote() == null ? "转储订单制单" : item.getNote():"转储订单终止",
                                transfer.getOriginLocation().getCompany())

        );
    }

    /**
     * 功能：提供界面传入ID参数查询
     *
     * @param request
     * @return
     */
    public Transfer findOne(SimpleRequest request) {
        Transfer innerTransfer = transferRepository.findOne((String) request.get("id"));
        if (innerTransfer == null) {
            List<Transfer> innerTransfers = transferRepository.findByIdAndState(request.get("id"), "confirmed");
            if (!innerTransfers.isEmpty()) {
                innerTransfer = innerTransfers.stream().findFirst().get();
            }
        }
        return innerTransfer;
    }

    /**
     * 功能：创建发货方交货单
     *
     * @param request 传入 转储订单的数据
     * @return Pick 交货单数据
     */
    public Pick createOriginPick(SimpleRequest request) {
        Transfer order = request.getO(Transfer.class);
        Pick pick = new Pick();
        pick.setCustomerExpandId(order.getCustomerExpandId());
        pick.setCreator("system");
        Enumeration enumeration = new Enumeration();
        enumeration.setId("direct");
        pick.setMoveType(enumeration);        // 交货方式 direct：部分交货，one： 一次性交货
        pick.setCompany(order.getOriginLocation().getCompany());    // 设置公司
        pick.setLocation(order.getOriginLocation());                // 设置仓库
        pick.setReceiptLocation(order.getReceiptLocation());
        pick.setPartner(order.getReceiptLocation().getCompany());              // 合作伙伴 收货方的公司

        pick.setAuto(order.checkAuto());  // 注入是否为自动收货

        pick.setOrigin(order.getId());
        pick.setOriginBusinessType(order.getInnerBusinessType());
        pick.setOperation("deliver");                   // 交货类型：发货
        pick.setScene(order.getScene());                // 注入场景

        Set<PickItem> pickItems = this.getPickItem(order);
        if (pickItems.isEmpty()) return new Pick();
        pick.setPickItems(pickItems);          // 添加明细
        return pick;
    }

    /**
     * 功能：获取明细数据
     *
     * @param innerTransfer
     * @return
     */
    private Set<PickItem> getPickItem(Transfer innerTransfer) {
        Set<PickItem> pickItems = innerTransfer.getTransferItems().stream().filter(transferItem -> {
            double surplusQty = transferItem.getTransferQty() - transferItem.getSendQty() - transferItem.getFinishSum();
            if (innerTransfer.getWithDrawDiveryQtySum() > 0) return surplusQty > 0 && transferItem.getWithDrawDiveryQty() > 0;
            return surplusQty > 0;
        }).map((TransferItem innerTransferItem) -> {
                    double withDrawDiveryQty = innerTransferItem.getWithDrawDiveryQty();
                    double orderQty = innerTransferItem.getTransferQty() - innerTransferItem.getSendQty();
                    double newQty = withDrawDiveryQty > 0?withDrawDiveryQty:orderQty;
                    PickItem pickItem = new PickItem();
                    pickItem.setProduct(innerTransferItem.getProduct());
                    pickItem.setUom(innerTransferItem.getUom());
                    pickItem.setOrderedQty(newQty) ;
                    pickItem.setProductUomQty(newQty);
                    pickItem.setOriginLine(String.valueOf(innerTransferItem.getId()));
                    return pickItem;
                }).collect(Collectors.toSet());
        return pickItems;
    }

    /**
     * 功能：创建收货方的交货单
     *
     * @param request 传入 订单的数据
     * @return Pick 交货单数据
     */
    private Pick createReceiptPick(SimpleRequest request) {
        Pick deliverPick = request.getO(Pick.class); // 交货单
        String transferOrderId = String.valueOf(deliverPick.getOrigin());
        Transfer order = transferRepository.findOne(transferOrderId);

        Enumeration enumeration = new Enumeration();
        enumeration.setId("one");
        Pick pick = new Pick();
        pick.setCreator(deliverPick.getDoneUid().getId());
        pick.setMoveType(enumeration);        // 交货方式 direct：部分交货，one： 一次性交货
        pick.setState("confirmed");        // 设置状态
        pick.setCompany(order.getReceiptLocation().getCompany());    // 设置公司
        pick.setLocation(order.getReceiptLocation());                // 设置仓库
        pick.setReceiptLocation(order.getOriginLocation());
        pick.setPartner(order.getOriginLocation().getCompany());              // 合作伙伴 收货方的公司
        pick.setCustomerExpandId(deliverPick.getCustomerExpandId());

        pick.setAuto(order.checkAuto());  // 注入是否为自动收货

        pick.setOrigin(order.getId());
        pick.setOriginBusinessType(order.getInnerBusinessType());
        pick.setOperation("receipt");                   // 交货类型：收货
        pick.setScene(order.getScene());                // 注入场景
        pick.setSource(deliverPick.getId());

        // 明细数据，使用交货单的数量作为收货方的收货数量
        Set<PickItem> pickItems = new HashSet<>();
        for (PickItem deliverPickItem : deliverPick.getPickItems()) {

            long result = order.getTransferItems().stream()
                    .filter(innerTransferItem -> innerTransferItem.getId() == Long.valueOf((String) deliverPickItem.getOriginLine()))
                    .map(innerTransferItem -> {
                        double qtyDone = ((Number) deliverPickItem.getQtyDone()).doubleValue();
                        PickItem pickItem = new PickItem();
                        pickItem.setOrderedQty(/*qtyDone*/innerTransferItem.getTransferQty());        // 获取数量
                        pickItem.setProduct(innerTransferItem.getProduct());
                        pickItem.setUom(innerTransferItem.getUom());
                        pickItem.setProductUomQty(qtyDone);
                        pickItem.setOriginLine(String.valueOf(innerTransferItem.getId()));

                        pickItems.add(pickItem);
                        return innerTransferItem;
                    }).count();
            if (result != 1) {
                throw new RuntimeException("采购单行号：" + deliverPickItem.getOriginLine() + " 输入错误！");
            }
        }
        pick.setPickItems(pickItems);
        return pick;
    }

    /**
     * 功能：提供给流程编排中创建收货方的交货单
     * 前置步骤：收货方的交货单发货
     *
     * @param request
     */
    public Pick createReceiptPickBySOE(SimpleRequest request) {
        String businessType = request.get("originBusinessType");
        // 判断是否为内部转储单
        if (!"Transfer".equals(businessType)) return null;

        Pick receiptPick = this.createReceiptPick(request);

        return (Pick) this.sendSynEvent("event:stock.pick.create", receiptPick).get(0);
    }

    /**
     * 功能：处理交货完成事件
     * 【【注意】】存在收货比发货回写状态快, 修改主表数据是需要注意收货比发货回写数据快，会导致状态错误
     */
    @Listener(topic = "event:stock.pick.delivery")
    public boolean delivery(SimpleRequest request) {
        JSONObject json = request.getJO();
        if (!json.getString("originBusinessType").equals(Transfer.class.getSimpleName())) return false;

        JSONObject itemQtyComplete = new JSONObject(); // 用来判断是否完成
        String operation = json.get("operation").toString();
        Transfer order = transferRepository.findOne(json.getString("origin"));
        for (Map requestItem : ((List<Map>) json.get("items"))) {
            AtomicBoolean existsPickItem = new AtomicBoolean(false); // 用来判断是否存在一条明细
            order.getTransferItems().stream().anyMatch(item -> {
                double qtyDone = ((Number) requestItem.get("qtyDone")).doubleValue();
                existsPickItem.set(item.getId() == Long.valueOf((String) requestItem.get("originItemId")));

                // 判断所有明细数量是否完成并存储
                if (itemQtyComplete.size() != order.getTransferItems().size()) itemQtyComplete.put(item.getId() + "", item.getTransferQty() == item.getFinishSum() + item.getQtyReceived());
                if (existsPickItem.get()) {
                    switch(operation) {
                        case "deliver":
                            deliverChangeData(order, item, qtyDone);
                            break;
                        case "receipt":
                            receiptChangeData(order, item, qtyDone);
                            changeDepositInTransit(order.getInnerBusinessType(), order.getInnerBusinessKey(), item.getId(), order.getOriginLocation(), order.getReceiptLocation());
                            break;
                        default:
                            System.out.println("跟我一起念：多么优美的代码!");
                    }
                    itemQtyComplete.put(item.getId() + "", item.getTransferQty() == item.getFinishSum() + item.getQtyReceived());
                }
                return existsPickItem.get();
            });
            if (!existsPickItem.get()) throw new RuntimeException("转储单行号：" + requestItem.get("originItemId") + " 输入错误！");
        }

        // 要货转储收发货
        /*Map param = new HashMap();
        param.put("pickId", json.get("pickId"));
        invoke("stock.autoProductRequireDumpService.receiptAndDelivery", param);*/

        // 设置状态，方式流程编排重新调用
        if (operation.equals("receipt")) { // 存在收货比发货回写状态快, 修改主表数据是需要注意收货比发货回写数据快，会导致状态错误
            order.setState(!itemQtyComplete.containsValue(false)?"done":order.getState());
        } else {
            order.setState("delivery");
        }

        transferRepository.saveAndFlush(order);
        return true;
    }


    // 发货变更数据
    private void deliverChangeData(Transfer order, TransferItem orderItem, double qtyDone) {
        // 写入库存账的转储发货在途、转储收货在途
        changeStock(order, orderItem, qtyDone, 1);

        // 减少收货仓的转入制单数
        changeInBilling(order,-1);

        // 回写转储单明细的已发货数量
        orderItem.setSendQty(orderItem.getSendQty() + qtyDone);
    }

    // 收货
    private void receiptChangeData(Transfer order, TransferItem orderItem, double qtyDone) {
        if (orderItem.getSendQty() == 0 || orderItem.getSendQty() - orderItem.getQtyReceived() == 0) throw new RuntimeException("发货数量还未写入成功，请耐心等待~");
        changeStock(order, orderItem, qtyDone, -1);
        orderItem.setQtyReceived(orderItem.getQtyReceived() + qtyDone);
    }

    // 更新未达账
    private void changeDepositInTransit(String innerBusinessType, String innerBusinessKey, long id, Location originLocation, Location receiptLocation) {
        depositInTransitService.delete(innerBusinessType, innerBusinessKey,
                String.valueOf(id), originLocation);
        depositInTransitService.delete(innerBusinessType, innerBusinessKey,
                String.valueOf(id), receiptLocation);
    }


    // 获取实际可用数
    public Double getUsableQtyToUom(SimpleRequest request) {
        JSONObject tempJson = request.getJO();
        String id = tempJson.getString("id");
        Location location = new Location();
        PartyRole company = new PartyRole();
        Product product = productRepository.findOne(tempJson.getJSONObject("product").getString("id"));
        ProductUom uom = productUomRepository.findOne(tempJson.getJSONObject("uom").getLong("id"));
        location.setId(tempJson.getJSONObject("location").getString("id"));
        company.setId(tempJson.getJSONObject("company").getString("id"));
        return getUsableQtyToUom(location, product, uom, company, id);
    }

    /***
     * 功能：获取实际可用数
     * @param location
     * @param product
     * @param uom
     * @param company
     * @return
     */
    public Double getUsableQtyToUom(Location location, Product product, ProductUom uom, PartyRole company, String id) {
        // 基础计量单位
        TransferItem transferItem = transferItemRepository.findOne(Long.valueOf(id));
        ProductUom baseUom = uomService.getUom(company, product);

        // 剩余可用数
        Double restUsableQty = 0.00;
        List<Stock> procuctList = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", product)));
        if (procuctList != null && procuctList.size() > 0) restUsableQty = procuctList.get(0).getUsableQty();

        // 已占用可用数
        Double occupyUsableQty = transferItem.getUom().computeQty(transferItem.getTransferQty(), baseUom, false);

        return baseUom.computeQty(occupyUsableQty + restUsableQty, uom, true);
    }

    /**
     * 导入
     */
    public JSONObject beImport(SimpleRequest request) {
        //Excel信息
        JSONObject importData = request.get("importData");
        JSONArray field = (JSONArray) request.get("data");
        JSONObject exclObject = new JSONObject();                  //返回值

        JSONArray exclArr = new JSONArray();            //行内容
        JSONArray headerName = new JSONArray();         //头部
        JSONArray fieldName = new JSONArray();          //field
        for (Object o : field) {
            JSONObject webTab = (JSONObject) o;
            headerName.add(webTab.get("name"));
            fieldName.add(webTab.get("field"));
        }

        //获取model
        JSONObject model = (JSONObject) request.get("model");
        String originLocationId = model.getJSONObject("originLocation").getString("id");
        Location originLocation = SpringManager.getBean(LocationRepository.class).findOne(originLocationId);

        ProductUomRepository productUomRepository = SpringManager.getBean(ProductUomRepository.class);

        //业务逻辑
        importData.forEach((k, v) -> {
            //获得value ===Excel内容
            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //首行数据
            String productId;
            double qty;
            for (int i = 0; i < excl.size(); i++) {  //遍历每一行

                if (i == 0) { //跳过首行
                    exclArr.add(headerName);
                    continue;
                }

                JSONArray lineLong = (JSONArray) excl.get(i); //当前行
                if (lineLong.size() == 0) {
                    continue; //跳过空白行
                }
                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
                Map<String, String> rst = IntStream.range(0, header.size()).collect(HashMap::new,
                        (m, key) -> m.put(header.getString(key).replace(";", ""),
                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? null : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
                        (m1, m2) -> {
                        });
                productId = rst.get("商品");
                if (Objects.isNull(rst.get("转储数量")) && Objects.isNull(rst.get("调拨数量"))) throw new RuntimeException("找不到转储数量（调拨数量）列，请检查导入文件的列名！");
                qty = Double.parseDouble(Objects.isNull(rst.get("转储数量")) ? rst.get("调拨数量") : rst.get("转储数量"));
                if (qty < 0) throw new RuntimeException("转储数量不能为负数！");

                Product product = SpringManager.getBean(ProductRepository.class).findOne(productId);
                Optional.ofNullable(product).orElseThrow(() -> new RuntimeException(String.format("商品[%s]不存在", rst.get("商品"))));

                //商品库存账
                Stock stock = stockRepository.findByProductAndLocation(product,originLocation);
                if (stock == null) throw new RuntimeException("仓库[" + originLocation.getId() + "]商品[" +productId + "]没有库存账,请检查");

                //默认转储单位
                ProductUom productUom = productUomRepository.findByProductId(productId);
                double canUseQty = stock.getProduct().getUom().computeQty(stock.getUsableQty(),productUom,false);
                if (canUseQty == 0 || canUseQty < qty) throw new RuntimeException("仓库[" + originLocation.getId() + "]商品[" +productId + "]可用数不足,请检查");

                //用一个有序的map 封装数据, 防止乱序
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("序号", "");
                map.put("订单行号", "");
                map.put("商品", product);
                map.put("单位", productUom);
                map.put("换算比率", 1/productUom.getFactor());
                map.put("税率", "");
                map.put("可用数",canUseQty);
                map.put("转储数量", qty);
                map.put("已发货数量", 0);
                map.put("已到货数量", 0);
                map.put("终止数量", 0);
                map.put("备注", "");
                //将map 转换成 list 利用stream流 引用Map类的getValue方法,弄成一个list
                List<Object> valueList = new ArrayList<>(map.values());
                exclArr.add(valueList);
            }

            exclObject.put(k, exclArr);
        });
        return exclObject;
    }

    /**
     * 查询框查询转储订单
     * @param request
     * @return
     */
    public Page findAllPrint(SimpleRequest request) {
        List<Map> condition = request.get("condition");
        Map param = condition.stream().filter(map -> "printState".equals(map.get("field").toString())).collect(Collectors.toList()).get(0);
        condition = condition.stream().filter(map -> !"printState".equals(map.get("field").toString())).collect(Collectors.toList());

        List<Transfer> transfers = transferRepository.findAll(JpaDsl.toCriteria(condition));
        convertData(transfers);
        if ("1".equals(param.get("value"))) {
            List<Transfer> notPrint = transfers.stream().filter(e -> e.getPrintNumber() == 0).collect(Collectors.toList());
            return autoPage(request,notPrint);
        } else if("2".equals(param.get("value"))) {
            List<Transfer> Print = transfers.stream().filter(e -> e.getPrintNumber() > 0).collect(Collectors.toList());
            return autoPage(request,Print);
        }
        return autoPage(request,transfers);
    }

    public void convertData(List<Transfer> transfers) {
        transfers.forEach(e->{
            double num = this.invoke("print.record.findOne",mapper("id",e.getId()));
            e.setPrintNumber(num);
        });
    }

    public Page autoPage(SimpleRequest request, List<Transfer> data) {
        List<Transfer> pageResult;
        int page = Integer.valueOf(request.get("page").toString());
        int size = Integer.valueOf(request.get("size").toString());
        if (data.size() < page*size) return null;
        if (data.size() <= size*(page +1)) {
            pageResult  = data.subList(page*size,data.size());
        }else {
            pageResult  = data.subList(page*size,size*(page +1));
        }
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        PageImpl pageImpl = new PageImpl<>(pageResult, pageable, data.size());
        return pageImpl;
    }

    /**修改转入制单数量*/
    public void changeInBilling(Transfer order,int typeValue) {
        order.getTransferItems().forEach(orderItem-> {
            productAccountService.setProductTransferInBilling(orderItem.getProduct(),
                    order.getReceiptLocation(), orderItem.getUom(), typeValue * orderItem.getTransferQty(),
                    order.getReceiptLocation().getCompany());
        });
    }

    // 交货单撤回
    public void pickWithdraw(SimpleRequest request) {
        Map pick = request.getMap();
        String pickOrigin = pick.get("origin").toString();
        Transfer transfer = transferRepository.findOne(pickOrigin);
        ((List) pick.get("item")).stream().forEach(pickI -> {
            Map pickItem = (Map) pickI;
            double pickQtyDone = Double.valueOf(pickItem.get("qtyDone").toString());
            transfer.getTransferItems().stream().anyMatch(transferI -> {
                if (Long.valueOf(pickItem.get("originItemId").toString()) == transferI.getId()) {
                    transfer.setItemQtyComplete(false);
                    transferI.setWithDrawDiveryQty(pickQtyDone);
                    transfer.setWithDrawDiveryQtySum(transfer.getWithDrawDiveryQtySum() + pickQtyDone);
                    transferI.setSendQty(transferI.getSendQty() - pickQtyDone); // 还原单据发货数量
                    changeStock(transfer, transferI, pickQtyDone, -1); // 减少收发货在途
                    // 增加保管数
                    productAccountService.setProductCustody(transferI.getProduct(), transfer.getOriginLocation(), transferI.getUom(),
                            Math.abs(pickQtyDone), transfer.getInnerBusinessType(), transfer.getId(), transferI.getId() + "", "交货撤回", transfer.getOriginLocation().getCompany());

                    // 增加转入制单数量
                    productAccountService.setProductTransferInBilling(transferI.getProduct(), transfer.getReceiptLocation(), transferI.getUom(), pickQtyDone,
                            transfer.getReceiptLocation().getCompany());
                    return true;
                }
                return false;
            });
        });
        //取消收货方交货单
        invoke("stock.pick.batchCancel", MapUtil.mapper("origin", pickOrigin, "source", pick.get("pickId").toString(), "cancelUid", pick.get("cancelUid")));

        // 通过场景流生成新的交货单生成新的交货单
        transfer.setState("approve");
        transferRepository.saveAndFlush(transfer);
    }

    public boolean externalCheckAuto(Location originLocation, Location receiptLocation){
        return originLocation.getDepot().getId().equals(receiptLocation.getDepot().getId());
    }


    // 修改其他扩展表数据
    public void updateOtherTable(Transfer transfer) {
        if (!"SafetyStockGap".equals(transfer.getSpecialDocumentsType())) return;
        transfer.getTransferItems().forEach(item -> {
            Map requireExpand = MapUtil.mapper("origin", transfer.getSpecialDocuments(), "originItemId", item.getOriginItemId(), "originBusinessType", transfer.getSpecialDocumentsType(),
                    "productId", MapUtil.mapper("id", item.getProduct().getId()), "productUomId", MapUtil.mapper("id", item.getUom().getId()),
                    "distributionId", transfer.getId(), "requireQty", item.getTransferQty(), "assignQty", item.getTransferQty());

            // 写入要货扩展表
            invoke("stock.productRequireExpand.save", requireExpand);

            // 修改安全库存分配数量
            this.sendUpdateGapAssignedQty(transfer.getSpecialDocumentsType(), item, item.getTransferQty());
        });
    }

    // 修改安全库存分配数量
    private void sendUpdateGapAssignedQty(String specialDocumentsType, TransferItem item, double currentQty) {
        if (!"SafetyStockGap".equals(specialDocumentsType)) return;
        invoke("stock.safetyStockGapService.updateAssignedQty",
                MapUtil.mapper("id", item.getOriginItemId(), "assignedQty", currentQty, "uom", MapUtil.mapper("id", item.getUom().getId())));
    }

    // 不考虑多次终止的情况
    private void stopSendUpdateRequireExpandAssignedQty(String transferId, String specialDocumentsType, TransferItem item) {
        if (!"SafetyStockGap".equals(specialDocumentsType)) return;
        Map requireExpand = MapUtil.mapper("originItemId", item.getOriginItemId(), "productId", MapUtil.mapper("id", item.getProduct().getId()), "productUomId", MapUtil.mapper("id", item.getUom().getId()),
                "distributionId", transferId, "cancelQty", item.getFinishSum());
        invoke("stock.productRequireExpandService.updateCancelQty", requireExpand);
    }


    // 【审核】要货批量转储修改要货明细、生成扩展表
    private void batchRequireDumpUpdateRequireQty(Transfer transfer) {
        if (StringUtils.isEmpty(transfer.getSpecialDocumentsType()) || !"要货补货转储新逻辑 - 后面要剔除".equals(transfer.getSpecialDocumentsType())) return;
        String requireIds = transfer.getBatchRequireId();
        Map data = MapUtil.mapper("id", transfer.getId(), "locationId", transfer.getReceiptLocation().getId(), "requireIds", requireIds, "specialDocumentsType", transfer.getSpecialDocumentsType(), "operate", "转储单审核",
                "operateInnerBusinessType", transfer.getInnerBusinessType());
        List items = transfer.getTransferItems().stream().map(transferItem -> {
            Map m = MapUtil.mapper("id", transferItem.getId(), "productId", transferItem.getProduct().getId(), "uomId", transferItem.getUom().getId(),
                    "qty", transferItem.getTransferQty());
            return m;
        }).collect(Collectors.toList());

        data.put("item", items);
        sendSynEvent("event:fn.crossCompanyTransferNewService.approve", new JSONObject(data));
    }

    // 【终止】要货批量转储修改要货明细、生成扩展表
    private void terminationNoticRequireAndRequireExpand(Transfer transfer) {
        if (StringUtils.isEmpty(transfer.getSpecialDocumentsType()) || !"要货补货转储新逻辑 - 后面要剔除".equals(transfer.getSpecialDocumentsType())) return;
        String requireIds = transfer.getBatchRequireId();
        Map data = MapUtil.mapper("id", transfer.getId(), "locationId", transfer.getReceiptLocation().getId(), "requireIds", requireIds,
                "specialDocumentsType", transfer.getSpecialDocumentsType(), "operate", "转储单终止", "operateInnerBusinessType", transfer.getInnerBusinessType());
        List items = transfer.getTransferItems().stream().map(transferItem -> {
            Map m = MapUtil.mapper("id", transferItem.getId(), "productId", transferItem.getProduct().getId(), "uomId", transferItem.getUom().getId(),
                    "qty", transferItem.getFinishSum());
            return m;
        }).collect(Collectors.toList());

        data.put("item", items);
        sendSynEvent("event:fn.crossCompanyTransferNewService.termination", new JSONObject(data));
    }

/*    @Listener(topic = "event:fn.crossCompanyTransferNewService.findSpecialDocumentsType")
    private String findSpecialDocumentsType(SimpleRequest request) {
        Transfer transfer = transferRepository.findOne(request.getJO().getString("id"));
        if (Objects.isNull(transfer)) return "";
        return transfer.getSpecialDocumentsType();
     }*/

    public JSONObject printOne (SimpleRequest request){
        String id = request.getJO().getString("id");
        Transfer transfer = transferRepository.findOne(request.getJO().getString("id"));
        List<TransferItem> transferItemLis = transferItemRepository.findTransferId(id);

        Map main = MapUtil.mapped(transfer);
        main.remove("transferItems");
        List<Map> transferItems = MapUtil.mapped(transferItemLis);
        for (int i = 0, iLen = transferItems.size(); i < iLen; i++) {
            Map singleTransferItem = transferItems.get(i);
            singleTransferItem.put("XH", i+1);
        }
        main.put("transferItems", transferItems);

        JSONObject transferObj = new JSONObject();
        transferObj.putAll(main);
        return transferObj;
    }
}
